package regex;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @fileName: CommonRegex
 * @author: Han
 * @date: 2018/6/8 11:21
 * @dscription: TODO
 */
public class CommonRegex {

    /**
     * 源码中需要清除的无用标签
     */
    private static String[] junkTag = {"a", "script", "style", "meta", "input", "button",
            "select", "br", "footer"};

    private static String preProcess(String html) {
        html = html.replaceAll("&amp;", "&");
        html = html.replaceAll("&lt;", "<");
        html = html.replaceAll("&gt;", ">");
        html = html.replaceAll("&quot;", "\"");
        html = html.replaceAll("&nbsp;", " ");

        // 去头
        html = html.replaceAll("<!DOCTYPE[\\s\\S]*?>", "");
        // 去注释
        html = html.replaceAll("<!--[\\s\\S]*?-->", "");
        // 去标题
        html = html.replaceAll("<title.*?>[\\s\\S]*?</title>", "");
        // 去特殊字符
        html = html.replaceAll("&.{2,6};|&#.{2,6};", " ");
        // 去标签属性
        html = html.replaceAll("<[\\s\\S]*?>", "");
        return html;
    }

    private static int getMax(ArrayList<Integer> indexDistribution) {
        int maxNum = 0;
        for (Integer anIndexDistribution : indexDistribution) {
            if (maxNum < anIndexDistribution) {
                maxNum = anIndexDistribution;
            }
        }
        return maxNum;
    }

    private static void clearTag(Document doc) {
        for (String tag : junkTag) {
            doc.select(tag).remove();
        }
    }

    public static String getSignalText(String pageContent) {
        //清除标签
        Document doc = Jsoup.parse(pageContent);
        clearTag(doc);
        doc.removeAttr("head");

        // 过滤html标签，替换特殊字符
        String html = preProcess(doc.html());
        // 以8行为一块检测最大行的单词数
        int blockSize = 8;
        // 阈值 和取text准确度相关
        int minWords = 128;
        //将源码用空格切分成list
        List<String> lines = Arrays.asList(html.split("\n+?"));

        //每8行的文字个数
        ArrayList<Integer> indexDistribution = new ArrayList<>();
        for (int i = 0; i < lines.size() - blockSize; i++) {
            int wordsNum = 0;
            for (int j = i; j < i + blockSize; j++) {
                //去除空格后的长度
                wordsNum += lines.get(j).replaceAll("\\s+", "").trim().length();
            }
            indexDistribution.add(wordsNum);
        }

        // 取出8行块中最大的一个值
        if (indexDistribution.size() != 0) {
            int maxWords = getMax(indexDistribution);
            // 对排序后最大的数值小于给定阙值的数据，进行行块值替换，保证数据抽取准确
            if (maxWords < minWords) {
                minWords = maxWords;
            }
        }

        int start = -1, end = -1;
        boolean boolstart = false, boolend = false;
        StringBuilder text = new StringBuilder();
        int indexDistributionSize = indexDistribution.size();
        // 以给定的阙值来获取正文,正文长度需要比阙值大
        for (int i = 0; i < indexDistribution.size() - 3; i++) {
            // 查找文本的开始点
            if (indexDistribution.get(i) >= minWords && !boolstart) {
                //行块值大于最小阈值并且还未获取到起点
                if (indexDistribution.get(i + 1) > 10
                        || indexDistribution.get(i + 2) > 10
                        || indexDistribution.get(i + 3) > 10) {
                    //临近的后面3个行块值是否都大于10个字符
                    boolstart = true;
                    start = i;

                    continue;

                }
            }

            // 查找文本文件的结束点
            if (boolstart) {
                //如果获取到了起点，则开始获取截止点
                if (indexDistribution.get(i) < 10
                        || indexDistribution.get(i + 1) < 10) {
                    end = i;
                    boolend = true;
                } else if (i == (indexDistributionSize - 4)) {
                    //当判断到最后没有结果的时候，让结束点等于最后的长度点 add zhouyh
                    end = i + 4;
                    boolend = true;
                }
            }

            // 获取正文，如果获取到起始点和结束点，则对切分后的text再进行拼接，形成一个完整的正文
            if (boolend) {
                StringBuilder tmp = new StringBuilder();
                for (int ii = start; ii <= end; ii++) {
                    if (lines.get(ii).length() == 0) {
                        continue;
                    }
                    tmp.append(lines.get(ii)).append("\n");
                }
                String str = tmp.toString();
                str = str.replaceAll("<.*?>", "");
                text.append(str);
                break;
            }
        }

        return text.toString().replaceAll("\n+", "\n").replaceAll("\r+", "\r")
                .replaceAll("\\s{2,}", "  ").trim();
    }

    public static String getAuthor(String pageContent) {
        String author = "null";/*Regex.matchString(pageContent,"<[^<][ \t\\S]*author[ \t\\S]*?[^>]>[\\s\\S]*?[^\n]
        (?=\n)");
        if ("null".equals(author)){
            author = Regex.matchString(pageContent,"<[^<][ \t\\S]*作者[ \t\\S]*?[^>]>[\\s\\S]*?[^\n](?=\n)");
        }*/
        if ("null".equals(author)){
            author = Regex.matchString(pageContent,"[ \t\\S]*作者[ \t\\S]*?[^>]>");
        }

        //author = author.replaceAll("<[\\S\\s]*?[^<>]>", "");
        return author;
    }

    public static void main(String... args) {

        BufferedReader reader = null;
        String page = "";
        try {
            StringBuilder pageSB = new StringBuilder();
            reader = new BufferedReader(new InputStreamReader(new FileInputStream("F:/test.txt")));
            String line;
            while ((line = reader.readLine()) != null) {
                pageSB.append(line).append("\n");
            }
            page = pageSB.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                Objects.requireNonNull(reader).close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(getAuthor(page));
    }
}
